home *** CD-ROM | disk | FTP | other *** search
- /*
- * xconv.c
- *
- * Practical Algorithms for Image Analysis
- *
- * Copyright (c) 1997, 1998, 1999 MLMSoftwareGroup, LLC
- */
-
- /*
- * XCONV(olve)
- *
- * test convolve.c module
- *
- */
-
- #include "xconv.h"
-
- #define BUFSZ 1024
- #define MAX_FILTER_LENGTH 65
- #undef FILTER_PRINT /* define this to print filter */
-
- /*
- * globals
- */
- extern short tiffInput; /* flag=0 if no ImageIn to set tags; else =1 */
- extern char *optarg;
- extern int optind, opterr;
-
- /*
- * usage of routine
- */
- void
- usage (char *progname)
- {
- progname = last_bs (progname);
- printf ("USAGE: %s inimg outimg [-f filter_file] [-g len] [-L]\n", progname);
- printf ("\n%s convolves an image with a kernel;\n", progname);
- printf ("kernels may be read from a filter file; Gaussian\n");
- printf ("kernels of any length can be generated automatically.\n\n");
- printf ("ARGUMENTS:\n");
- printf (" inimg: intput image filename (TIF)\n");
- printf (" outimg: output image filename (TIF)\n\n");
- printf ("OPTIONS:\n");
- printf (" -f filter_file: filename for filter to use (ASCII)\n");
- printf (" -g len: use 2-D Gaussian filter of length len\n");
- printf (" NOTE: either -f or -g must be specified\n");
- printf (" -L: print Software License for this module\n");
- exit (1);
- }
-
-
- #undef FILTER_TEST
-
- Matrix *
- genGaussFilter (char *filterLenStr)
- {
- Matrix *retMatrix;
- float *ip, **ipp;
- int ix, iy;
- int i;
- int nf2;
- float two_sigma_sq;
- float x;
- float sigma;
- float *filter1D;
- float norm;
- int filterLen;
-
- if (!sscanf (filterLenStr, "%d", &filterLen)) {
- printf ("Can't scan gaussian filter length\n");
- exit (1);
- }
- if (filterLen > MAX_FILTER_LENGTH || filterLen < 0) {
- printf ("\n...filter length too long!! forget it!!\n");
- exit (1);
- }
-
- filterLen = (filterLen % 2 > 0 ? filterLen : (filterLen + 1));
- sigma = (float) filterLen / (float) (3.0 * 2.0);
- nf2 = filterLen / 2;
- norm = (float) 0.0;
-
- if ((retMatrix = (struct Matrix *) calloc (1, sizeof (struct Matrix))) == NULL) {
- printf ("\n...mem allocation for retMatrix failed\n");
- exit (1);
- }
- if ((ipp = (float **) calloc (filterLen, sizeof (float *))) == NULL) {
- printf ("\n...mem allocation for ipp failed\n");
- exit (1);
- }
- if ((ip = (float *) calloc (filterLen * filterLen, sizeof (float))) == NULL) {
- printf ("\n...mem allocation for ip failed\n");
- exit (1);
- }
- if ((filter1D = (float *) calloc (filterLen, sizeof (float))) == NULL) {
- printf ("\n...mem allocation for filter1D failed\n");
- exit (1);
- }
- for (iy = 0; iy < filterLen; iy++)
- ipp[iy] = ip + (iy * filterLen);
- retMatrix->matrix = ipp;
- /*
- * Generate a 1-D Gaussian
- */
- two_sigma_sq = (float) 2.0 *sigma * sigma;
- for (i = 0; i < filterLen; i++) {
- x = (float) (i - filterLen / 2);
- *(filter1D + i) = (float) (255.0 * exp (-(x * x) / two_sigma_sq));
- norm += *(filter1D + i);
- }
- norm = (float) fabs ((double) norm);
-
- /*
- * Now create the 2-D kernel
- */
- for (iy = 0; iy < filterLen; iy++)
- for (ix = 0; ix < filterLen; ix++)
- ipp[iy][ix] = (*(filter1D + iy) * *(filter1D + ix));
- #ifdef FILTER_PRINT
- printf ("...sigma = %f\n", sigma);
- printf ("...filter length = %d\n", filterLen);
- printf ("...kernel coefficients:\n");
- for (iy = 0; iy < filterLen; iy++) {
- for (ix = 0; ix < filterLen; ix++)
- printf ("%5.5f ", ipp[iy][ix]);
- printf ("\n");
- }
- #endif
- retMatrix->nRows = filterLen;
- retMatrix->nCols = filterLen;
- return (retMatrix);
- }
-
- Matrix *
- readFilter (char *filename)
- {
- FILE *stream;
- int nx, ny;
- Matrix *retMatrix;
- float *ip, **ipp;
- int ix, iy;
- char *sptr, inBuf[BUFSZ];
- char seps[] = " ,\t\n";
- char *token;
-
- if ((stream = fopen (filename, "r")) != NULL) {
- for (;;) {
- if (fgets (inBuf, BUFSZ, stream) == (char *) NULL) {
- printf ("Premature EOF encountered while reading filter file %s\n", filename);
- exit (1);
- }
- /*
- * Throw away comments
- */
- if (inBuf[0] == '#')
- continue;
- else {
- if (sscanf (inBuf, "%d %d\n", &nx, &ny) != 2) {
- printf ("error getting kernel size\n");
- exit (1);
- }
- if ((retMatrix = (struct Matrix *) calloc (1, sizeof (struct Matrix))) == NULL) {
- printf ("\n...mem allocation for retMatrix failed\n");
- exit (1);
- }
- if ((ipp = (float **) calloc (ny, sizeof (float *))) == NULL) {
- printf ("\n...mem allocation for ipp failed\n");
- exit (1);
- }
- if ((ip = (float *) calloc (ny * nx, sizeof (float))) == NULL) {
- printf ("\n...mem allocation for ip failed\n");
- exit (1);
- }
- for (iy = 0; iy < ny; iy++)
- ipp[iy] = ip + (iy * nx);
- retMatrix->matrix = ipp;
- break;
- }
- }
- /*
- * Now read the kernel in
- */
- for (iy = 0; iy < ny; iy++) {
- if (fgets (inBuf, BUFSZ, stream) == (char *) NULL) {
- printf ("Premature EOF encountered while reading filter file %s\n", filename);
- exit (1);
- }
- /*
- * Throw away comments
- */
- if (inBuf[0] == '#')
- continue;
- sptr = inBuf;
- for (ix = 0; ix < nx; ix++) {
- if ((token = strtok (sptr, seps)) == (char *) NULL) {
- printf ("Can't read filter values on line %d of file %s\n", iy + 2, filename);
- exit (1);
- }
- if (!sscanf (token, "%f", &(ipp[iy][ix]))) {
- printf ("Can't scan filter values on line %d of file %s\n", iy + 2, filename);
- exit (1);
- }
- sptr = NULL;
- }
- }
- fclose (stream);
- retMatrix->nRows = ny;
- retMatrix->nCols = nx;
- for (iy = 0; iy < ny; iy++) {
- for (ix = 0; ix < nx; ix++)
- printf ("%5.5f ", ipp[iy][ix]);
- printf ("\n");
- }
- return (retMatrix);
- }
- else {
- printf ("Can not open kernel file: %s\n", filename);
- exit (1);
- }
- }
-
- int
- main (int argc, char *argv[])
- {
-
- Image *imgIn, *imgOut;
- Matrix *kernelp;
- int kernel_gauss = 0;
- int kernel_file = 0;
- int i_arg;
-
- /*
- * cmd line options:
- */
- static char *optstring = "f:g:L";
-
- /*
- * parse command line
- */
- optind = 3;
- opterr = ON; /* give error messages */
-
- if (argc < 4)
- usage (argv[0]);
-
- while ((i_arg = getopt (argc, argv, optstring)) != EOF) {
- switch (i_arg) {
- case 'f':
- /*
- * Read in filter from file
- */
- kernelp = readFilter (optarg);
- kernel_file = 1;
- break;
- case 'g':
- /*
- * Generate 2-D Gaussian
- */
- kernelp = genGaussFilter (optarg);
- kernel_gauss = 1;
- break;
- case 'L':
- print_sos_lic ();
- exit (0);
- default:
- usage (argv[0]);
- break;
- }
- }
- if (kernel_gauss && kernel_file) {
- printf ("Please specify either -f OR -g option, not both!\n");
- exit (1);
- }
- /*
- * read input image
- */
- imgIn = ImageIn (argv[1]);
- if (imgIn->bps == 8 && imgIn->spp == 3) {
- printf ("Got RGB image!!!\nInput image must be Grayscale or B&W!!\n");
- exit (1);
- }
- /* reset tiffInput so that we write a grayscale file (i.e tags are not copied) */
- tiffInput = 0;
- /*
- * Allocate memory for output image
- */
- imgOut = ImageAlloc (imgIn->height, imgIn->width, imgIn->bps);
-
- printf ("Doing image convolution...\n");
- /*
- * Do the convolution
- */
- convolve (imgIn, imgOut, kernelp);
- /*
- * Write the output image
- */
- ImageOut (argv[2], imgOut);
- return (1);
- }
-